home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
6366
/
6366.xpi
/
components
/
xdGestureHandler.js
< prev
next >
Wrap
Text File
|
2009-11-17
|
17KB
|
536 lines
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const PREFS_DOMAIN = "extensions.firegestures.";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const STATE_READY = 0;
const STATE_GESTURE = 1;
const STATE_ROCKER = 2;
const STATE_WHEEL = 3;
const STATE_KEYPRESS = 4;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function xdGestureHandler() {}
xdGestureHandler.prototype = {
classDescription: "Mouse Gesture Handler",
contractID: "@xuldev.org/firegestures/handler;1",
classID: Components.ID("{ca559550-8ab4-41c5-a72f-fd931322cc7e}"),
QueryInterface: XPCOMUtils.generateQI([
Ci.nsISupports,
Ci.nsIObserver,
Ci.nsISupportsWeakReference,
Ci.nsIDOMEventListener,
Ci.nsITimerCallback,
Ci.xdIGestureHandler
]),
sourceNode: null,
_drawArea: null,
_lastX: null,
_lastY: null,
_directionChain: "",
_gestureObserver: null,
attach: function FGH_attach(aDrawArea, aObserver) {
this._drawArea = aDrawArea;
this._gestureObserver = aObserver;
this._drawArea.addEventListener("mousedown", this, true);
this._drawArea.addEventListener("mousemove", this, true);
this._drawArea.addEventListener("mouseup", this, true);
this._drawArea.addEventListener("contextmenu", this, true);
this._drawArea.addEventListener("draggesture", this, true);
this._reloadPrefs();
var prefBranch2 = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch2);
prefBranch2.addObserver(PREFS_DOMAIN, this, true);
},
detach: function FGH_detach() {
this._drawArea.removeEventListener("mousedown", this, true);
this._drawArea.removeEventListener("mousemove", this, true);
this._drawArea.removeEventListener("mouseup", this, true);
this._drawArea.removeEventListener("contextmenu", this, true);
this._drawArea.removeEventListener("draggesture", this, true);
var prefBranch2 = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch2);
prefBranch2.removeObserver(PREFS_DOMAIN, this);
this._clearTimeout();
this.sourceNode = null;
this._drawArea = null;
this._gestureObserver = null;
this._prefs = null;
},
_reloadPrefs: function FGH__reloadPrefs() {
var prefBranch = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService)
.getBranch(PREFS_DOMAIN);
var getPref = function(aName) {
try {
switch (prefBranch.getPrefType(aName)) {
case prefBranch.PREF_STRING:
return prefBranch.getCharPref(aName);
case prefBranch.PREF_BOOL:
return prefBranch.getBoolPref(aName);
case prefBranch.PREF_INT:
return prefBranch.getIntPref(aName);
default:
throw null;
}
}
catch(ex) {
}
};
this._triggerButton = getPref("trigger_button");
this._suppressAlt = getPref("suppress.alt");
this._trailEnabled = getPref("mousetrail");
this._trailSize = getPref("mousetrail.size");
this._trailColor = getPref("mousetrail.color");
this._gestureTimeout = getPref("gesture_timeout");
this._mouseGestureEnabled = getPref("mousegesture");
this._wheelGestureEnabled = getPref("wheelgesture");
this._rockerGestureEnabled = getPref("rockergesture");
this._keypressGestureEnabled = getPref("keypressgesture");
this._drawArea.removeEventListener("DOMMouseScroll", this, true);
this._drawArea.removeEventListener("click", this, true);
if (this._wheelGestureEnabled)
this._drawArea.addEventListener("DOMMouseScroll", this, true);
if (this._rockerGestureEnabled)
this._drawArea.addEventListener("click", this, true);
var tabbrowser = this._drawArea.ownerDocument.getBindingParent(this._drawArea);
if (tabbrowser && tabbrowser.localName == "tabbrowser") {
tabbrowser.mStrip.removeEventListener("DOMMouseScroll", this._wheelOnTabBar, true);
if (getPref("tabwheelgesture"))
tabbrowser.mStrip.addEventListener("DOMMouseScroll", this._wheelOnTabBar, true);
}
if (this._triggerButton == 1) {
var prefSvc = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch2)
.QueryInterface(Ci.nsIPrefService);
prefSvc.setBoolPref("middlemouse.contentLoadURL", false);
}
},
_state: STATE_READY,
_isMouseDownL: false,
_isMouseDownM: false,
_isMouseDownR: false,
_suppressContext: false,
_shouldFireContext: false,
handleEvent: function FGH_handleEvent(event) {
switch (event.type) {
case "mousedown":
if (event.button == 0) {
var targetName = event.target.localName.toUpperCase();
if (targetName == "INPUT" || targetName == "TEXTAREA") {
break;
}
targetName = event.originalTarget.localName;
if (targetName == "scrollbarbutton" || targetName == "slider" || targetName == "thumb") {
break;
}
this._isMouseDownL = true;
this._isMouseDownM = false;
if (this._triggerButton == 0 && !this._isMouseDownM && !this._isMouseDownR && !this._altKey(event)) {
this._state = STATE_GESTURE;
this._startGesture(event);
if (this._mouseGestureEnabled)
event.preventDefault();
}
else if (this._rockerGestureEnabled && this._isMouseDownR) {
this._state = STATE_ROCKER;
this._invokeExtraGesture(event, "rocker-left");
}
}
else if (event.button == 1) {
this._isMouseDownM = true;
if (this._triggerButton == 1 && !this._isMouseDownL && !this._isMouseDownR && !this._altKey(event)) {
this._state = STATE_GESTURE;
this._startGesture(event);
event.stopPropagation();
}
}
else if (event.button == 2) {
var targetName = event.target.localName.toUpperCase();
if (targetName == "OBJECT" || targetName == "EMBED") {
break;
}
this._isMouseDownR = true;
this._isMouseDownM = false;
this._suppressContext = false;
if (this._triggerButton == 2 && !this._isMouseDownL && !this._isMouseDownM && !this._altKey(event)) {
this._state = STATE_GESTURE;
this._startGesture(event);
}
else if (this._rockerGestureEnabled && this._isMouseDownL) {
this._state = STATE_ROCKER;
this._invokeExtraGesture(event, "rocker-right");
}
}
break;
case "mousemove":
if (this._state == STATE_GESTURE || this._state == STATE_KEYPRESS) {
if (this._mouseGestureEnabled) {
if (this._keypressGestureEnabled && (event.ctrlKey || event.shiftKey)) {
var type = this._state == STATE_GESTURE ? "keypress-start" : "keypress-progress";
this._state = STATE_KEYPRESS;
this._invokeExtraGesture(event, type);
}
this._progressGesture(event);
}
}
else if (this._state == STATE_WHEEL || this._state == STATE_ROCKER) {
this._lastX = event.screenX;
this._lastY = event.screenY;
if (Math.abs(this._lastX - this._lastExtraX) > 10 ||
Math.abs(this._lastY - this._lastExtraY) > 10) {
this._stopGesture();
}
}
break;
case "mouseup":
if (event.button == 0)
this._isMouseDownL = false;
else if (event.button == 1)
this._isMouseDownM = false;
else if (event.button == 2)
this._isMouseDownR = false;
if (!this._isMouseDownL && !this._isMouseDownM && !this._isMouseDownR) {
if (this._state == STATE_KEYPRESS) {
this._state = STATE_READY;
if (event.ctrlKey)
this._invokeExtraGesture(event, "keypress-ctrl");
else if (event.shiftKey)
this._invokeExtraGesture(event, "keypress-shift");
this._invokeExtraGesture(event, "keypress-stop");
}
this._stopGesture(event);
if (this._shouldFireContext) {
this._shouldFireContext = false;
this._displayContextMenu(event);
}
}
break;
case "contextmenu":
if (!this._isMouseDownL && this._isMouseDownR) {
this._suppressContext = true;
this._shouldFireContext = true;
}
if (this._suppressContext) {
this._suppressContext = false;
event.preventDefault();
event.stopPropagation();
}
break;
case "DOMMouseScroll":
if (this._state == STATE_GESTURE || this._state == STATE_WHEEL) {
this._state = STATE_WHEEL;
this._invokeExtraGesture(event, event.detail < 0 ? "wheel-up" : "wheel-down");
event.preventDefault();
event.stopPropagation();
}
break;
case "click":
if (this._state == STATE_ROCKER) {
event.preventDefault();
event.stopPropagation();
}
break;
case "draggesture":
if (this._state != STATE_ROCKER)
this._isMouseDownL = false;
break;
}
},
_altKey: function(event) {
return this._suppressAlt ? event.altKey : false;
},
_displayContextMenu: function FGH__displayContextMenu(event) {
with (this._drawArea.ownerDocument.defaultView) {
if (!nsContextMenu.prototype._setTargetInternal) {
nsContextMenu.prototype._setTargetInternal = nsContextMenu.prototype.setTarget;
nsContextMenu.prototype.setTarget = function(aNode, aRangeParent, aRangeOffset) {
this._setTargetInternal(aNode, aRangeParent, this._rangeOffset);
};
}
nsContextMenu.prototype._rangeOffset = event.rangeOffset;
}
var evt = event.originalTarget.ownerDocument.createEvent("MouseEvents");
evt.initMouseEvent(
"contextmenu", true, true, event.originalTarget.ownerDocument.defaultView, 0,
event.screenX, event.screenY, event.clientX, event.clientY,
false, false, false, false, 2, null
);
event = new XPCNativeWrapper(event);
event.originalTarget.dispatchEvent(evt);
},
_wheelOnTabBar: function FGH__wheelOnTabBar(event) {
var tabbar = null;
if (event.target.localName == "tab")
tabbar = event.target.parentNode;
else if (event.target.localName == "tabs" && event.originalTarget.localName != "menuitem")
tabbar = event.target;
else
return;
event.preventDefault();
event.stopPropagation();
tabbar.advanceSelectedTab(event.detail < 0 ? -1 : 1, true);
},
_startGesture: function FGH__startGesture(event) {
this.sourceNode = event.target;
this._lastX = event.screenX;
this._lastY = event.screenY;
this._directionChain = "";
this._shouldFireContext = false;
if (this._trailEnabled)
this.createTrail(event);
},
_progressGesture: function FGH__progressGesture(event) {
var x = event.screenX;
var y = event.screenY;
var dx = Math.abs(x - this._lastX);
var dy = Math.abs(y - this._lastY);
if (dx < 10 && dy < 10)
return;
var direction;
if (dx > dy)
direction = x < this._lastX ? "L" : "R";
else
direction = y < this._lastY ? "U" : "D";
if (this._trailEnabled)
this.drawTrail(this._lastX, this._lastY, x, y);
this._lastX = x;
this._lastY = y;
if (this._state == STATE_KEYPRESS)
return;
var lastDirection = this._directionChain.charAt(this._directionChain.length - 1);
if (direction != lastDirection) {
this._directionChain += direction;
this._gestureObserver.onDirectionChanged(event, this._directionChain);
}
if (this._gestureTimeout > 0)
this._setTimeout(this._gestureTimeout);
},
_invokeExtraGesture: function FGH__invokeExtraGesture(event, aGestureType) {
if (this._state == STATE_WHEEL || this._state == STATE_ROCKER) {
this._lastExtraX = event.screenX;
this._lastExtraY = event.screenY;
}
if (this._state != STATE_KEYPRESS && this._trailEnabled)
this.eraseTrail();
this._gestureObserver.onExtraGesture(event, aGestureType);
this._suppressContext = true;
this._shouldFireContext = false;
this._directionChain = "";
if (this._state == STATE_WHEEL || this._state == STATE_ROCKER) {
if (this._gestureTimeout > 0)
this._setTimeout(this._gestureTimeout);
}
},
_stopGesture: function FGH__stopGesture(event) {
this._state = STATE_READY;
this._isMouseDownL = false;
this._isMouseDownM = false;
this._isMouseDownR = false;
if (this._trailEnabled)
this.eraseTrail();
if (this._directionChain) {
this._gestureObserver.onMouseGesture(event, this._directionChain);
this._suppressContext = true;
this._shouldFireContext = false;
}
this.sourceNode = null;
this._directionChain = "";
this._clearTimeout();
},
observe: function FGH_observe(aSubject, aTopic, aData) {
if (aTopic == "nsPref:changed")
this._reloadPrefs();
},
_gestureTimer: null,
_setTimeout: function FGH__setTimeout(aMsec) {
this._clearTimeout();
this._gestureTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._gestureTimer.initWithCallback(this, aMsec, Ci.nsITimer.TYPE_ONE_SHOT);
},
_clearTimeout: function FGH__clearTimeout() {
if (this._gestureTimer) {
this._gestureTimer.cancel();
this._gestureTimer = null;
}
},
notify: function(aTimer) {
this._suppressContext = true;
this._shouldFireContext = false;
this._directionChain = "";
this._stopGesture();
this._gestureObserver.onExtraGesture(null, "gesture-timeout");
},
openPopupAtPointer: function FGH_openPopupAtPointer(aPopup) {
aPopup.openPopupAtScreen(this._lastX, this._lastY, false);
this._directionChain = "";
this._stopGesture();
},
_trailDot: null,
_trailArea: null,
_trailLastDot: null,
_trailOffsetX: 0,
_trailOffsetY: 0,
_trailZoom: 1,
createTrail: function FGH_createTrail(event) {
var doc;
if (event.view.top.document instanceof Ci.nsIDOMHTMLDocument)
doc = event.view.top.document;
else if (event.view.document instanceof Ci.nsIDOMHTMLDocument)
doc = event.view.document;
else
return;
var insertionNode = doc.documentElement ? doc.documentElement : doc;
if (doc.getBoxObjectFor) {
var box = doc.getBoxObjectFor(insertionNode);
this._trailOffsetX = box.screenX;
this._trailOffsetY = box.screenY;
this._trailZoom = 1;
var tabbrowser = this._drawArea.ownerDocument.defaultView.gBrowser;
if (tabbrowser && (tabbrowser.mCurrentBrowser || tabbrowser).markupDocumentViewer.fullZoom != 1) {
var dot = doc.createElementNS(HTML_NS, "xdTrailDot");
dot.style.top = "1048576px";
dot.style.position = "absolute";
insertionNode.appendChild(dot);
this._trailZoom = (doc.getBoxObjectFor(dot).screenY - this._trailOffsetY) / dot.offsetTop;
insertionNode.removeChild(dot);
}
}
else {
var win = doc.defaultView;
this._trailZoom = win.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils).screenPixelsPerCSSPixel;
this._trailOffsetX = (win.mozInnerScreenX - win.scrollX) * this._trailZoom;
this._trailOffsetY = (win.mozInnerScreenY - win.scrollY) * this._trailZoom;
}
this._trailArea = doc.createElementNS(HTML_NS, "xdTrailArea");
insertionNode.appendChild(this._trailArea);
this._trailDot = doc.createElementNS(HTML_NS, "xdTrailDot");
this._trailDot.style.width = this._trailSize + "px";
this._trailDot.style.height = this._trailSize + "px";
this._trailDot.style.background = this._trailColor;
this._trailDot.style.border = "0px";
this._trailDot.style.position = "absolute";
this._trailDot.style.zIndex = 2147483647;
},
drawTrail: function FGH_drawTrail(x1, y1, x2, y2) {
if (!this._trailArea)
return;
var xMove = x2 - x1;
var yMove = y2 - y1;
var xDecrement = xMove < 0 ? 1 : -1;
var yDecrement = yMove < 0 ? 1 : -1;
x2 -= this._trailOffsetX;
y2 -= this._trailOffsetY;
if (Math.abs(xMove) >= Math.abs(yMove))
for (var i = xMove; i != 0; i += xDecrement)
this._strokeDot(x2 - i, y2 - Math.round(yMove * i / xMove));
else
for (var i = yMove; i != 0; i += yDecrement)
this._strokeDot(x2 - Math.round(xMove * i / yMove), y2 - i);
},
eraseTrail: function FGH_eraseTrail() {
if (this._trailArea && this._trailArea.parentNode) {
while (this._trailArea.lastChild)
this._trailArea.removeChild(this._trailArea.lastChild);
this._trailArea.parentNode.removeChild(this._trailArea);
}
this._trailDot = null;
this._trailArea = null;
this._trailLastDot = null;
},
_strokeDot: function FGH__strokeDot(x, y) {
if (this._trailArea.y == y && this._trailArea.h == this._trailSize) {
var newX = Math.min(this._trailArea.x, x);
var newW = Math.max(this._trailArea.x + this._trailArea.w, x + this._trailSize) - newX;
this._trailArea.x = newX;
this._trailArea.w = newW;
this._trailLastDot.style.left = newX.toString() + "px";
this._trailLastDot.style.width = newW.toString() + "px";
return;
}
else if (this._trailArea.x == x && this._trailArea.w == this._trailSize) {
var newY = Math.min(this._trailArea.y, y);
var newH = Math.max(this._trailArea.y + this._trailArea.h, y + this._trailSize) - newY;
this._trailArea.y = newY;
this._trailArea.h = newH;
this._trailLastDot.style.top = newY.toString() + "px";
this._trailLastDot.style.height = newH.toString() + "px";
return;
}
if (this._trailZoom != 1) {
x = Math.floor(x / this._trailZoom);
y = Math.floor(y / this._trailZoom);
}
var dot = this._trailDot.cloneNode(true);
dot.style.left = x + "px";
dot.style.top = y + "px";
this._trailArea.x = x;
this._trailArea.y = y;
this._trailArea.w = this._trailSize;
this._trailArea.h = this._trailSize;
this._trailArea.appendChild(dot);
this._trailLastDot = dot;
},
};
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule([xdGestureHandler]);
}